package com.wxg.address.view;

import com.wxg.address.MainApp;
import com.wxg.address.model.Person;
import com.wxg.address.util.DateUtil;

import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;

/**
 * 1) 所有fxml文件需要访问的属性和方法必须加上 `@FXML` 注解. 实际上,只有在私有的情况下才需要,
 * 但是让它们保持私有并且用注解标记的方式更好！<br>
 * 2) `initialize()` 方法在fxml文件完成载入时被自动调用. 那时,所有的FXML属性都应该已经被初始化
 * 3) 我们在表格列上使用 `setCellValueFactory(...)`来确定为特定列使用`Person`对象的某个属性.
 * 箭头 `->` 表示我们使用Java8的 Lambdas 特性. (另一个选择是使用 PropertyValueFactory, 但它不是类型安全的).<br>
 *
 * 4) 使用"SceneBuilder"打开`PersonOverview.fxml`.
 * 在"Controller"组选择`PersonOverviewController`作为 controller class.
 * 在"Hierarchy"组选择`TableView`并选择 Code 组将`personTable`作为 "fx:id"
 * 对列作同样的事情.<br>
 * 5) 重要事项: 回到eclipse并且 refresh the entire AddressApp project (F5).
 * 这是必要的,因为有时候eclipse并不知道Scene Builder中作出的改变.<br>
 * 6) 在JavaFX中有一个接口称为`ChangeListener`, 带有一个方法`changed()`
 *
 * @author Wxg
 *
 */
public class PersonOverviewController {
	@FXML
	private TableView<Person> personTable;

	@FXML
	private TableColumn<Person, String> firstNameColumn;
	@FXML
	private TableColumn<Person, String> lastNameColumn;

	@FXML
	private Label firstNameLabel;
	@FXML
	private Label lastNameLabel;
	@FXML
	private Label streetLabel;
	@FXML
	private Label postalCodeLabel;
	@FXML
	private Label cityLabel;
	@FXML
	private Label birthdayLabel;

	// Reference to the main application.
	private MainApp mainApp;

	/**
	 * The constructor.
	 * The constructor is called before the initialize() method.
	 */
	public PersonOverviewController(){}

	/**
	 * Initializes the controller class. This method is automatically called
	 * after the fxml file has been loaded.<br>
	 *
	 * 添加监听。不管什么时候用户选择表中的人员,都会执行我们的 lambda 表达式。
	 * 我们获取新选择的人员,并且把它传递给`showPersonDetails(...)`
	 *
	 */
	@FXML
	private void initialize(){
		// Initialize the person table with the two columns.
		firstNameColumn.setCellValueFactory(cellData -> cellData.getValue().getFirstName());
		lastNameColumn.setCellValueFactory(cellData -> cellData.getValue().getLastName());

		// Clear person details.
		showPersonDetails(null);

		// Listen for sellection changes and show the person details when changed.
		personTable.getSelectionModel().selectedItemProperty().addListener(
				(observable, oldValue, newValue) -> showPersonDetails(newValue));
	}

	/**
	 * Is called by the main application to give a reference back to itself.
	 *
	 * @param mainApp
	 */
	public void setMainApp(MainApp mainApp){
		this.mainApp = mainApp;

		// Add observable list data to the table
		personTable.setItems(mainApp.getPersonData());
	}

	/**
	 * Fills all text fields to show details about the person.
	 * If the specified person is null, all text fields are cleared.
	 *
	 * @param person
	 */
	private void showPersonDetails(Person person){
		if (person != null) {
			// Fill the labels with info
			firstNameLabel.setText(person.getFirstName().getValue());
			lastNameLabel.setText(person.getLastName().getValue());
			streetLabel.setText(person.getStreet().getValue());
			postalCodeLabel.setText(person.getPostalCode().getValue().toString());
			cityLabel.setText(person.getCity().getValue());
			// TODO: We need a way to convert the birthday into a String!
			// birthdayLabel.setText();
			birthdayLabel.setText(DateUtil.format(person.getBirthday().getValue()));
		} else{
			// Person is null, remove all the text.
			firstNameLabel.setText("");
			lastNameLabel.setText("");
			streetLabel.setText("");
			postalCodeLabel.setText("");
			cityLabel.setText("");
			birthdayLabel.setText("");
		}
	}

	/**
	 * Called when the user clicks on the delete button.
	 * 在我们控制器中的任何使用`@FXML`(或者它是公用的)注释的方法都可以被"Scene Builder"访问.
	 */
	@FXML
	private void handleDeletePerson() {
		int selectedIndex = personTable.getSelectionModel().getSelectedIndex();
		if(selectedIndex >= 0){
			personTable.getItems().remove(selectedIndex);
		}else{
			/**
			 * [JavaFX Dialog实现（JDK8）](http://blog.csdn.net/u010889616/article/details/53057047)
			 * 这里使用的是 Alert, 没有按照教程中使用"Dialog"
			 */
			// Nothing selected.
			Alert alert = new Alert(AlertType.INFORMATION);
			alert.setTitle("No Selection");
			alert.setHeaderText("No Person Selected");
			alert.setContentText("Please select a person in the table.");

			alert.showAndWait();
		}
	}

	/**
	 * Called when the user clicks the new button. Opens a dialog to edit
	 * details for a new person.
	 */
	@FXML
	private void handleNewPerson(){
		Person tempPerson = new Person();
		boolean okClicked = mainApp.showPersonEditDialog(tempPerson);
		if(okClicked){
			mainApp.getPersonData().add(tempPerson);
		}
	}

	/**
	 * Called when the user clicks the edit button. Opens a dialog to edit
	 * details for the selected person.
	 */
	@FXML
	private void handleEditPerson(){
		Person selectedPerson = personTable.getSelectionModel().getSelectedItem();
		if(selectedPerson != null){
			boolean okClicked = mainApp.showPersonEditDialog(selectedPerson);
			if(okClicked){
				showPersonDetails(selectedPerson);
			}
		}else{
			// Nothing selected.
			Alert alert = new Alert(AlertType.INFORMATION);
			alert.setTitle("No Selection");
			alert.setHeaderText("No Person Selected");
			alert.setContentText("Please select a person in the table.");

			alert.showAndWait();
		}
	}

}
